<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Collections.Specialized" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="OSGeo.MapGuide" %>
<!-- #Include File="markupmanager.aspx -->

<script language="c#" runat="server">
    public class MarkupEditor
    {
        private bool _hasProjectIdField = false;
        private MgResourceService _resourceService;
        private MgFeatureService _featureService;
        
        private string libraryPath;

        private NameValueCollection args = null;
        private MgSiteConnection site = null;

        public MarkupEditor(NameValueCollection incomingArgs)
        {
            this.args = incomingArgs;
            this.site = new MgSiteConnection();
            this.site.Open(new MgUserInformation(GetParameter(this.args, "SESSION")));
            
            _resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);
            _featureService = (MgFeatureService)this.site.CreateService(MgServiceType.FeatureService);

            if (!string.IsNullOrEmpty(GetParameter(this.args, "DIR")))
                libraryPath = GetParameter(this.args, "DIR");
            else
            {

                MgMap map = new MgMap();
                map.Open(_resourceService, GetParameter(this.args, "MAPNAME"));
                string path = map.MapDefinition.Path;
                if (path.ToLower().EndsWith("maps")) path = path.Substring(0, path.Length - 4);
                /*libraryPath = Path.Combine(String.Format("Library://{0}", path), "Markup/");*/
                 libraryPath = "Library://" + path + "/Markup/";
            }
            FeatureHasProjectIdField();
        }

        public String GetMarkupLayer()
        {
            return GetParameter(this.args, "OPENMARKUP");
        }

        public String GetMarkupName()
        {
            MgResourceIdentifier resId = new MgResourceIdentifier(this.GetMarkupLayer());
            return resId.GetName();
        }

        public Hashtable GetMarkupFeatures()
        {
            Hashtable features = new Hashtable();

            MgResourceIdentifier featureSourceId = new MgResourceIdentifier(libraryPath + this.GetMarkupName() + ".FeatureSource");

            MgFeatureReader featureReader = _featureService.SelectFeatures(featureSourceId, "Markup", null);
            while (featureReader.ReadNext())
            {
                String id = featureReader.GetInt32("ID").ToString();
                String text = featureReader.GetString("Text").Trim();
                features[id] = text;
            }
            return features;
        }

        public MgCoordinateSystemTransform GetTransform()
        {
            MgCoordinateSystemFactory coordSysFactory = new MgCoordinateSystemFactory();
            _resourceService = (MgResourceService)this.site.CreateService(MgServiceType.ResourceService);

            MgMap map = new MgMap();
            map.Open(_resourceService, GetParameter(this.args, "MAPNAME"));

            MgCoordinateSystem source = coordSysFactory.Create(map.GetMapSRS());
            //MgCoordinateSystem target = coordSysFactory.Create(MarkupManager.LL84WKT);
            MgCoordinateSystem target = coordSysFactory.Create(map.GetMapSRS());

            return coordSysFactory.GetTransform(source, target);
        }

        public void AddPoint()
        {
            MgGeometryFactory geometryFactory = new MgGeometryFactory();
            MgAgfReaderWriter agfWriter = new MgAgfReaderWriter();

            String[] vertices = GetParameter(this.args, "GEOMETRY").Split(new Char[] { ',' });

            MgCoordinate coord = geometryFactory.CreateCoordinateXY(Double.Parse(vertices[0]), Double.Parse(vertices[1]));
            MgPoint point = geometryFactory.CreatePoint(coord);
            point = (MgPoint)point.Transform(this.GetTransform());
            MgByteReader byteReader = agfWriter.Write(point);

            MgPropertyCollection propertyValues = CreatePropertyCollection(byteReader);

            this.InsertMarkupFeature(propertyValues);
        }

        public void AddLineString()
        {
            MgGeometryFactory geometryFactory = new MgGeometryFactory();
            MgAgfReaderWriter agfWriter = new MgAgfReaderWriter();

            String[] vertices = GetParameter(this.args, "GEOMETRY").Split(new Char[] { ',' });
            int count = (int)Double.Parse(vertices[0]);

            MgCoordinateCollection coords = new MgCoordinateCollection();
            for (int i = 0; i < count; i++)
            {
                MgCoordinate coord = geometryFactory.CreateCoordinateXY(Double.Parse(vertices[(i * 2) + 1]), Double.Parse(vertices[(i * 2) + 2]));
                coords.Add(coord);
            }

            MgLineString lineString = geometryFactory.CreateLineString(coords);
            lineString = (MgLineString)lineString.Transform(this.GetTransform());
            MgByteReader byteReader = agfWriter.Write(lineString);

            MgPropertyCollection propertyValues = CreatePropertyCollection(byteReader);

            this.InsertMarkupFeature(propertyValues);
        }

        public void AddPolygon()
        {
            MgGeometryFactory geometryFactory = new MgGeometryFactory();
            MgAgfReaderWriter agfWriter = new MgAgfReaderWriter();
            String[] vertices = GetParameter(this.args, "GEOMETRY").Split(new Char[] { ',' });
            int count = (int)Double.Parse(vertices[0]);

            MgCoordinateCollection coords = new MgCoordinateCollection();
            for (int i = 0; i < count; i++)
            {
                MgCoordinate coord = geometryFactory.CreateCoordinateXY(Double.Parse(vertices[(i * 2) + 1]), Double.Parse(vertices[(i * 2) + 2]));
                coords.Add(coord);
            }

            MgLinearRing linearRing = geometryFactory.CreateLinearRing(coords);
            MgPolygon polygon = geometryFactory.CreatePolygon(linearRing, null);
            polygon = (MgPolygon)polygon.Transform(this.GetTransform());
            MgByteReader byteReader = agfWriter.Write(polygon);

            MgPropertyCollection propertyValues = CreatePropertyCollection(byteReader);

            this.InsertMarkupFeature(propertyValues);
        }

        public void AddBuffer()
        {
            MgMap map = new MgMap();
            map.Open(_resourceService, GetParameter(this.args, "MAPNAME"));

            MgSelection selection = new MgSelection(map);
            selection.Open(_resourceService, map.Name);

            MgReadOnlyLayerCollection layers = selection.GetLayers();
            if (layers != null && layers.Count == 1)
            {
                MgFeatureQueryOptions opt = new MgFeatureQueryOptions();
                opt.SetFilter(selection.GenerateFilter(layers[0], layers[0].FeatureClassName));
                MgFeatureReader featureReader = _featureService.SelectFeatures(new MgResourceIdentifier(layers[0].FeatureSourceId), layers[0].FeatureClassName, opt);
                MgAgfReaderWriter agfRW = new MgAgfReaderWriter();

                MgGeometryCollection inputGeometries = new MgGeometryCollection();

                MgClassDefinition classDef = _featureService.GetClassDefinition(
                    new MgResourceIdentifier(layers[0].FeatureSourceId),
                    layers[0].FeatureClassName.Split(':')[0], 
                    layers[0].FeatureClassName.Split(':')[1]);

                while (featureReader.ReadNext())
                {
                    MgByteReader byteReader = featureReader.GetGeometry(classDef.DefaultGeometryPropertyName);
                    MgGeometry geom = agfRW.Read(byteReader);
                    inputGeometries.Add(geom);
                }

                if (inputGeometries.Count > 0)
                {
                    MgCoordinateSystemFactory coordSysFactory = new MgCoordinateSystemFactory();

                    MgCoordinateSystem mapSrs = coordSysFactory.Create(map.MapSRS);
                    double distance = mapSrs.ConvertMetersToCoordinateSystemUnits(7.0);
                    MgCoordinateSystemMeasure measure = mapSrs.GetMeasure();

                    MgGeometryFactory geomFactory = new MgGeometryFactory();
                    MgGeometry buffer = geomFactory.CreateMultiGeometry(inputGeometries).Buffer(distance, measure);

                    if (buffer != null)
                    {
                        MgByteReader byteReader = agfRW.Write(buffer);

                        MgGeometryFactory geometryFactory = new MgGeometryFactory();
                        MgAgfReaderWriter agfWriter = new MgAgfReaderWriter();

                        MgPropertyCollection propertyValues = CreatePropertyCollection(byteReader);

                        this.InsertMarkupFeature(propertyValues);
                    }
                }
            }
        }
        private MgPropertyCollection CreatePropertyCollection(MgByteReader byteReader)
        {
            MgPropertyCollection propertyValues = new MgPropertyCollection();
            
            propertyValues.Add(new MgStringProperty("Text", GetParameter(this.args, "TEXT")));
            propertyValues.Add(new MgStringProperty("ReverseText", ReverseString(GetParameter(this.args, "TEXT"))));
            if (_hasProjectIdField)
            {
                propertyValues.Add(new MgInt32Property("ProjectId", GetProjectId()));
            }
            propertyValues.Add(new MgGeometryProperty("Geometry", byteReader));
            
            return propertyValues;
        }
        public void InsertMarkupFeature(MgPropertyCollection propertyValues)
        {
            MgResourceIdentifier featureSourceId = new MgResourceIdentifier(libraryPath + this.GetMarkupName() + ".FeatureSource");

            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
            commands.Add(new MgInsertFeatures("Markup", propertyValues));
            
            _featureService.UpdateFeatures(featureSourceId, commands, false);
            int projectId = GetProjectId();
            if (projectId > 0)
            {
                using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["ProjectManagerConnectionString"].ConnectionString))
                {
                    var cmd = conn.CreateCommand();
                    cmd.CommandText = String.Format("INSERT INTO Projects(UID, ProjectId, StatusId) VALUES({0}, {1}, 1)", GetLastUID(featureSourceId), projectId);
                    conn.Open();
                    cmd.ExecuteNonQuery();
                }
            }
        }

        public bool DeleteMarkup()
        {
            MgResourceIdentifier featureSourceId = new MgResourceIdentifier(libraryPath + this.GetMarkupName() + ".FeatureSource");
            
            
            MgMap map = new MgMap();
            map.Open(_resourceService, GetParameter(this.args, "MAPNAME"));
            
            string path = map.MapDefinition.Path;
            if (path.ToLower().EndsWith("maps")) path = path.Substring(0, path.Length - 4);
            path = Path.Combine(String.Format("Library://{0}", path), "Maintenance/Data/Maintenance.FeatureSource");
            MgResourceIdentifier maintenanceResId = new MgResourceIdentifier(path);
            
            //Check related entries in maintenance
            if (MaintenanceForFeatureExists(featureSourceId, maintenanceResId)) return false;
            DeleteProjectDataFormDatabase(featureSourceId, GetParameter(this.args, "MARKUPFEATURE"));
            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
            commands.Add(new MgDeleteFeatures("Markup", "ID = " + GetParameter(this.args, "MARKUPFEATURE")));

            _featureService.UpdateFeatures(featureSourceId, commands, false);

            return true;
        }

        public void UpdateMarkup()
        {
            MgResourceIdentifier featureSourceId = new MgResourceIdentifier(libraryPath + this.GetMarkupName() + ".FeatureSource");

            MgPropertyCollection propertyValues = new MgPropertyCollection();
            propertyValues.Add(new MgStringProperty("Text", GetParameter(this.args, "UPDATETEXT")));
            propertyValues.Add(new MgStringProperty("ReverseText", ReverseString(GetParameter(this.args, "UPDATETEXT"))));

            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
            commands.Add(new MgUpdateFeatures("Markup", propertyValues, "ID = " + GetParameter(this.args, "MARKUPFEATURE")));

            _featureService.UpdateFeatures(featureSourceId, commands, false);
        }

        public String GetSelectionXML()
        {
            MgMap map = new MgMap();
            map.Open(_resourceService, GetParameter(this.args, "MAPNAME"));
            MgLayerBase markupLayer = map.GetLayers().GetItem("_" + this.GetMarkupName());

            MgSelection selection = new MgSelection(map);
            selection.AddFeatureIdInt32(markupLayer, "MarkupSchema:Markup", Int32.Parse(GetParameter(this.args, "MARKUPFEATURE")));

            return selection.ToXml();
        }

        public string ReverseString(string str)
        {
            try
            {
                int rtn = Convert.ToInt32(str);
                return Convert.ToString(rtn);
            }
            catch (Exception e)
            {
                int len = str.Length;
                char[] arr = new char[len];

                for (int i = 0; i < len; i++)
                {
                    arr[i] = str[len - 1 - i];
                }

                return new string(arr);
            }
        }
        private void FeatureHasProjectIdField()
        {
            MgResourceIdentifier featureSourceId = new MgResourceIdentifier(libraryPath + this.GetMarkupName() + ".FeatureSource");
            MgClassDefinition classDef = _featureService.GetClassDefinition(featureSourceId, "MarkupSchema", "Markup");
            _hasProjectIdField = classDef.GetProperties().Contains("ProjectId");
        }
        private int GetProjectId()
        {
            int result = 0;
            if (_hasProjectIdField)
            {
                MgResourceIdentifier featureSourceId = new MgResourceIdentifier(libraryPath + this.GetMarkupName() + ".FeatureSource");
                using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["ProjectManagerConnectionString"].ConnectionString))
                {
                    var cmd = conn.CreateCommand();
                    cmd.CommandText = String.Format("SELECT Id FROM ProjectCollections WHERE FeatureId = '{0}'", featureSourceId.ToString());
                    cmd.CommandType = System.Data.CommandType.Text;
                    conn.Open();
                    using (var reader = cmd.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            result = (int)reader["Id"];
                        }
                    }
                }
            }
            return result;
        }
        private int GetLastUID(MgResourceIdentifier resId)
        {
            int uid = 0;
            MgFeatureAggregateOptions opt = new MgFeatureAggregateOptions();
            opt.AddComputedProperty("UID", "MAX(\"UID\")");
            MgDataReader reader = _featureService.SelectAggregate(resId, "MarkupSchema:Markup", opt);
            if (reader.ReadNext())
            {
                uid = reader.GetInt32("UID");
            }
            return uid;
        }

        private bool MaintenanceForFeatureExists(MgResourceIdentifier featureSourceId, MgResourceIdentifier maintenanceResId)
        {
            bool result = false;
            if (_resourceService.ResourceExists(maintenanceResId))
            {
                MgFeatureQueryOptions opt = new MgFeatureQueryOptions();
                opt.SetFilter(String.Format("FeatureSource='{0}' AND UID = {1}", featureSourceId.ToString(), GetParameter(this.args, "MARKUPFEATURE")));

                MgFeatureReader reader = _featureService.SelectFeatures(maintenanceResId, "Maintenance:Maintenance", opt);
                if (reader.ReadNext())
                {
                    result = true;
                }
            }
            return result;
        }
        private void DeleteProjectDataFormDatabase(MgResourceIdentifier featureId, string uid)
        {
            using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["ProjectManagerConnectionString"].ConnectionString))
            {
                var cmd = conn.CreateCommand();
                cmd.CommandText = String.Format("SELECT p.Id FROM Projects as p INNER JOIN ProjectCollections as pc ON p.ProjectId = pc.Id WHERE pc.FeatureId = '{0}' AND p.UID = {1}", featureId.ToString(), uid);
                cmd.CommandType = System.Data.CommandType.Text;
                conn.Open();
                object result = cmd.ExecuteScalar();
                if (result != null)
                {
                    int id = (int)result;
                    cmd.CommandText = String.Format("DELETE FROM Projects WHERE Id={0}", id);
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
</script>

